package com.atwisdom.star.service.production.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.util.UuidTool;
import com.atwisdom.star.common.vo.ActionData;
import com.atwisdom.star.common.vo.JsonResult;
import com.atwisdom.star.common.vo.ResultInfo;
import com.atwisdom.star.core.bsl.modelClass.hier.impl.HierInstanceBslServiceImpl;
import com.atwisdom.star.core.bsl.modelClass.logic.Impl.LogicInstanceBslServiceImpl;
import com.atwisdom.star.core.bsl.modelClass.resource.Impl.ResourceInstanceBslServiceImpl;
import com.atwisdom.star.core.bsl.modelClass.tank.Impl.TankInstanceBslServiceImpl;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierInstance;
import com.atwisdom.star.core.dao.pojo.modelClass.logic.LogicInstance;
import com.atwisdom.star.core.dao.pojo.modelClass.workCenter.WorkCenterInstance;
import com.atwisdom.star.core.dsl.modelClass.hier.Impl.HierInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.resource.Impl.ResourceInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.routing.Impl.RoutingInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.tank.Impl.TankInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.workCenter.Impl.WorkCenterInstanceDslServiceImpl;
import com.atwisdom.star.exception.pojo.BusinessException;
import com.atwisdom.star.service.business.Routing;
import com.atwisdom.star.service.business.Tank;
import com.atwisdom.star.service.business.WorkCenter;
import com.atwisdom.star.service.pojo.BasicStatus;
import com.atwisdom.star.service.production.MasterPlanService;
import com.atwisdom.star.service.status.ProductionPlanStatus;
import com.atwisdom.star.service.status.RoutingPlanStatus;
import com.atwisdom.star.service.status.SalesOrderStatus;
import com.atwisdom.star.service.util.InstanceDataUtil;
import com.atwisdom.star.service.util.LogicUtil;
import com.atwisdom.star.service.util.RoutingUtil;
import com.atwisdom.star.service.util.ValidateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName: masterPlanServiceImpl
 * @ Description: 主计划
 * @author:王红艳
 * @date: 2024/05/17 12:30
 */
@Service
public class MasterPlanServiceImpl implements MasterPlanService {
    @Autowired
    private LogicInstanceBslServiceImpl logicInstanceBslServiceImpl;

    @Autowired
    private LogicInstanceDslServiceImpl logicInstanceDslServiceImpl;

    @Autowired
    private HierInstanceDslServiceImpl hierInstanceDslServiceImpl;

    @Autowired
    private HierInstanceBslServiceImpl hierInstanceBslServiceImpl;

    @Autowired
    ResourceInstanceBslServiceImpl resourceInstanceBslServiceImpl;

    @Autowired
    private ResourceInstanceDslServiceImpl resourceInstanceDslServiceImpl;

    @Autowired
    private WorkCenterInstanceDslServiceImpl workCenterInstanceDslServiceImpl;

    @Autowired
    private RoutingInstanceDslServiceImpl routingInstanceDslServiceImpl;

    @Autowired
    private TankInstanceBslServiceImpl tankInstanceBslServiceImpl;

    @Autowired
    private TankInstanceDslServiceImpl tankInstanceDslServiceImpl;

    @Autowired
    private LogicUtil logicUtil;

    @Autowired
    private RoutingUtil routingUtil;

    private final String planClassName = "MasterPlan";
    private final String planType = "staticLogic";
    private final String planModel = "staticLogic";
    private final String productionClassName = "ProductionPlan";
    private final String productionType = "logic";
    private final String productionModel = "logic";
    private final String salesOrderClassName = "SalesOrder";
    private final String salesOrderType = "production";
    private final String salesOrderModel = "resource";
    private final String noticeClassName = "WorkNotice";
    private final String noticeType = "logic";
    private final String noticeModel = "logic";
    private final String tankClassName = "Tank";
    private final String tankType = "tank";
    private final String tankModel = "tank";
    private final String materialClassName = "MaterialDetail";
    private final String materialType = "material";
    private final String materialModel = "resource";
    private final Long planId = Long.valueOf("54");
    private final String planParentId = "root";
    private final String endStatus = "结束";
    private final String productionRequireOrderParentId = "5a0bwe3kcfo000";
    private final String productionOrderParentId = "2z7ih39mttk000";
    private final String productionRoutingParentId = "5pmn0o6pg08000";
    private final String productionApproveParentId = "5taj9q7aa1k000";
    private final String routingModel = "routing";
    private final String workCenterModel = "workCenter";

    /**
     * 更新计划状态
     * @param id 实例id
     * @param status 状态
     */
    public void updatePlanStatus(Long id,String status){
        ProductionPlanStatus planStatus = new ProductionPlanStatus(id);
        planStatus.setUpdateStatus(planStatus.getStatusKey(),status);
        if(status.equals(planStatus.getStatus())){//状态不变不做更改
            return;
        }
        if(BasicStatus.PRODUCTION_PLAN_STATUS_FINISH.equals(status)&&!getEndFlag(id)){//更新完成，生产计划没有全部完成，不进行更新
            return;
        }
        planStatus.next();
        dealRoutingStatus(id,status);
        dealSalesOrderStatus(id,status);
    }

    /**
     * 获取生产计划是否全部完成状态
     * @param id 计划id
     * @return 是否全部完成状态
     */
    private boolean getEndFlag(Long id) {
        boolean endFlag = true;
        LogicInstance logicInstance = logicInstanceDslServiceImpl.queryInsWithHierById(id);
        List<HierInstance> routingHierList = logicInstance.getHierInstances().stream().filter(hierInstance -> productionRoutingParentId.equals(hierInstance.getParentId())&&null!=hierInstance.getLinkId()).collect(Collectors.toList());
        for(HierInstance hierInstance:routingHierList){
            RoutingPlanStatus routingPlanStatus = new RoutingPlanStatus(hierInstance.getLinkId());
            if(!routingPlanStatus.checkStatus(BasicStatus.ROUTING_PLAN_STATUS_FINISH)){
                endFlag = false;
                break;
            }
        }
        return endFlag;
    }

    /**
     * 处理主计划下生产计划的状态
     * @param id 主计划id
     * @param status 更新状态值
     */
    private void dealRoutingStatus(Long id,String status){
        LogicInstance logicInstance = logicInstanceDslServiceImpl.queryInsWithHierById(id);
        logicInstance.getHierInstances().stream().filter(hierInstance -> productionRoutingParentId.equals(hierInstance.getParentId())&&null!=hierInstance.getLinkId())
                .forEach(hierInstance ->{
                    Routing routing = new Routing();
                    routing.setRouting(hierInstance.getLinkId());
                    routing.updateRoutingStatus(routing.getRouting().getId(),status);
                });
    }
    /**
     * 处理主计划下订单的状态
     * @param id 主计划id
     * @param status 更新状态值
     */
    private void dealSalesOrderStatus(Long id,String status){
        if(!BasicStatus.SALES_ORDER_STATUS_MAKING.equals(status)&&!BasicStatus.SALES_ORDER_STATUS_IN_WAREHOUSE.equals(status)&&!BasicStatus.SALES_ORDER_STATUS_FINISH.equals(status)){
            return;
        }
        LogicInstance logicInstance = logicInstanceDslServiceImpl.queryInsWithHierById(id);
        logicInstance.getHierInstances().stream().filter(hierInstance -> productionOrderParentId.equals(hierInstance.getParentId())&&null!=hierInstance.getLinkId())
                .forEach(hierInstance ->{
                    updateOrderStatus(hierInstance.getLinkId(),status);
                });
    }
    /**
     * 更新计划状态
     * @param id 实例id
     * @param status 状态
     */
    public void updatePlanApproveStatus(Long id,String status,String checkStatus){
        ProductionPlanStatus planStatus = new ProductionPlanStatus(id);
        planStatus.setUpdateStatus(planStatus.getApproveStatusKey(),status);
        planStatus.next(planStatus.checkStatus(checkStatus));
    }

    /**
     * 更新计划状态
     * @param id 实例id
     * @param status 状态
     */
    public void updateRoutingPlanStatus(Long id,String status){
        RoutingPlanStatus planStatus = new RoutingPlanStatus(id);
        planStatus.setUpdateStatus(planStatus.getStatusKey(),status);
        planStatus.next();
    }
    /**
     * 更新计划状态
     * @param id 实例id
     * @param status 状态
     */
    public void updateRoutingPlanApproveStatus(Long id,String status,String checkStatus){
        RoutingPlanStatus planStatus = new RoutingPlanStatus(id);
        planStatus.setUpdateStatus(planStatus.getApproveStatusKey(),status);
        planStatus.next(planStatus.checkStatus(checkStatus));
    }

    /**
     * 更新订单状态
     * @param id 实例id
     * @param status 状态
     */
    public void updateOrderStatus(Long id,String status){
        SalesOrderStatus orderStatus = new SalesOrderStatus(id);
        if(status.equals(orderStatus.getStatus())){//状态不变不做更改
            return;
        }
        orderStatus.setUpdateStatus(orderStatus.getStatusKey(),status);
        orderStatus.next();
    }

    /**
     * 回退订单状态
     * @param id 实例id
     * @param status 状态
     */
    public void updateOrderStatusBack(Long id,String status){
        SalesOrderStatus orderStatus = new SalesOrderStatus(id);
        orderStatus.setUpdateStatus(orderStatus.getStatusKey(),status);
        orderStatus.back();
    }

    /**
     * 新增生产计划
     * 若生产计划类型为合批计划，则同时初始化一个需求订单，订单类型为需求订单，数量为0
     * @param data 计划数据
     * @return 计划数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> addProductionPlan(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(data.getJSONObject("values"),data.getJSONObject("values").getString("planType"));
        JSONObject productionPlanJson = logicInstanceDslServiceImpl.add(data);
        String planType = JsonUtil.get(productionPlanJson,"values.planType").toString();
        if(planType.contains("合批")||planType.contains("碳化钨")){
            JSONObject values = JsonUtil.buildJson(new Object[]{"orderForm","需求订单","productId",JsonUtil.get(data,"values.productId"),"batchNo",JsonUtil.get(data,"values.planBatchNo"),"weight",0});
            JSONObject orderJson = resourceInstanceDslServiceImpl.add(salesOrderType,salesOrderClassName, UuidTool.getUUID32(),values);
            JSONObject hierInsJson = JsonUtil.buildJson(new Object[]{"containerModel",this.productionModel,"containerClassName",this.productionClassName,"containerId",JsonUtil.get(productionPlanJson,"id"),"parentId",this.productionRequireOrderParentId,"linkId",JsonUtil.get(orderJson,"id"),"linkType",JsonUtil.get(orderJson,"type"),"linkClassName",JsonUtil.get(orderJson,"className"),"values",JsonUtil.get(orderJson,"values")});
            hierInstanceDslServiceImpl.addChild(hierInsJson);
        }
        JSONObject hierInsJson = JsonUtil.buildJson(new Object[]{"containerModel",this.planModel,"containerClassName",this.planClassName,"containerId",this.planId,"parentId",this.planParentId,"linkId",JsonUtil.get(productionPlanJson,"id"),"linkType",JsonUtil.get(productionPlanJson,"type"),"linkClassName",JsonUtil.get(productionPlanJson,"className"),"values",JsonUtil.get(productionPlanJson,"values")});
        JSONObject json = hierInstanceDslServiceImpl.convertToJson(hierInstanceDslServiceImpl.addChild(hierInsJson));
        return JsonResult.success(json);
    }

    /**
     * 查询计划数据，并将hier下的数据对应的values查询出来放入
     * @param data 计划数据
     * @return 处理后的计划数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> queryProductionPlanAndHier(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(data.getLong("id"));
        return JsonResult.success(logicUtil.queryByIdAndHier(data.getLong("id")));
    }

    /**
     * 订单分页查询，过滤掉被占用的数据
     * @param actionData 分页查询参数
     * @return 分页数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> querySalesOrderNotLinkByPage(JSONObject actionData)  throws BusinessException {
        ValidateUtil.hasEmpty(actionData.get("condition"),actionData.get("product"));
        List<HierInstance> hierList = hierInstanceDslServiceImpl.queryLink(productionModel,productionClassName,productionOrderParentId,salesOrderModel,salesOrderClassName,null);
        List<String> linkIds = InstanceDataUtil.listLongToListString(InstanceDataUtil.getLinkIdsByHierList(hierList));
        dealCondition(actionData, linkIds, "id not in");
        List<String> productIds = InstanceDataUtil.listLongToListString(queryProductIdByCategoryName(JsonUtil.get(actionData,"product").toString()));
        dealCondition(actionData, productIds, "productId in");
        return resourceInstanceBslServiceImpl.queryByPage(JsonUtil.toJavaBean(actionData,ActionData.class));
    }

    /**
     * 计划绑定订单，并更新订单状态
     * @param actionData 参数
     * @return 绑定数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> addSalesOrderLinkToProductionPlan(ActionData<JSONObject> actionData) throws BusinessException{
        List<JSONObject> datas = actionData.getData();
        if(CollectionUtil.isEmpty(datas)){
            return JsonResult.error(500,"绑定订单数据不能为空");
        }
        for(JSONObject data: datas){
            updateOrderStatus(Long.valueOf(JsonUtil.get(data,"linkId").toString()),BasicStatus.SALES_ORDER_STATUS_PLANNED);
        }
        String productId = JsonUtil.get(resourceInstanceDslServiceImpl.queryById(Long.valueOf(JsonUtil.get(datas.get(0),"linkId").toString())),"values.productId").toString();
        JSONObject jsonObject = JsonUtil.buildJson(new Object[]{"id",JsonUtil.get(datas.get(0),"containerId"),"values",JsonUtil.buildJson(new Object[]{"productId",productId})});
        logicInstanceDslServiceImpl.updateById(jsonObject);
        ResultInfo<?> resultInfo = hierInstanceBslServiceImpl.saveHierWithoutModel(actionData);
        dealRequiredOrder(Long.valueOf(JsonUtil.get(datas.get(0),"containerId").toString()));
        return resultInfo;
    }

    /**
     * 计划解除绑定订单，并更新订单状态
     * @param actionData 参数
     * @return 解绑是否成功标识
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> deleteSalesOrderLinkToProductionPlan(JSONObject actionData) throws BusinessException{
        ValidateUtil.hasEmpty(actionData.get("linkIds"),actionData.get("ids"),actionData.get("containerId"));
        List<Long> linkIds = JSONObject.parseArray(actionData.getJSONArray("linkIds").toJSONString(),Long.class);
        for(Long id:linkIds) {
            updateOrderStatusBack(id, BasicStatus.SALES_ORDER_STATUS_ENABLE);
        }
        List<Long> ids = JSONObject.parseArray(actionData.getJSONArray("ids").toJSONString(),Long.class);
        hierInstanceDslServiceImpl.deleteByIdList(ids);
        dealRequiredOrder(Long.valueOf(JsonUtil.get(actionData,"containerId").toString()));
        return JsonResult.success(ids);
    }

    /**
     * 更新计划状态
     * @param data 计划数据
     * @return 更新后数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> updateProductionPlanStatus(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(JsonUtil.get(data,"id"),JsonUtil.get(data,"status"));
        Long id = Long.valueOf(JsonUtil.get(data,"id").toString());
        updatePlanStatus(id,JsonUtil.get(data,"status").toString());
        return JsonResult.success(logicInstanceDslServiceImpl.queryJsonById(id));
    }

    /**
     * 审批计划
     * data示例：{"pointer":{"className":"","type":"","id":""},"approveValues":{"operatorId":"","operatorName":"","operateTime":"","action":"","status":"","opinions":""}}
     * @param data
     * @return
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> approveProductionPlan(JSONObject data)  throws BusinessException {
        ValidateUtil.hasEmpty(data.getJSONObject("pointer"),data.getJSONObject("approveValues"));//校验参数
        JSONObject approveValues = data.getJSONObject("approveValues");
        ValidateUtil.hasEmpty(approveValues.get("operatorId"),approveValues.get("operatorName"),approveValues.get("operateTime"),approveValues.get("action"),approveValues.get("status"),approveValues.get("opinions"));//校验参数
        JSONObject pointer = data.getJSONObject("pointer");
        ValidateUtil.hasEmpty(data.get("id"),data.get("className"),data.get("type"));//校验参数
        Long id = Long.valueOf(pointer.getString("id"));
        String status = approveValues.getString("status");
        if(BasicStatus.APPROVE_STATUS_REVIEW_RETURN.equals(status)){
            updatePlanApproveStatus(id,status,BasicStatus.PRODUCTION_PLAN_STATUS_ENABLE);
            updatePlanStatus(id,BasicStatus.PRODUCTION_PLAN_STATUS_CREATE);
        }else{
            updatePlanApproveStatus(id,status,BasicStatus.PRODUCTION_PLAN_STATUS_CREATE);
        }
        if(BasicStatus.APPROVE_STATUS_APPROVE.equals(status)){
            updatePlanStatus(id,BasicStatus.PRODUCTION_PLAN_STATUS_ENABLE);
        }
        logicUtil.addHier(productionApproveParentId,id,null,approveValues);
        return JsonResult.success(logicInstanceDslServiceImpl.queryJsonById(id));
    }

    /**
     * 更新需求订单数据
     * @param data 需求订单数据
     * @return 更新后数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> updateRequireSalesOrder(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(JsonUtil.get(data,"id"),JsonUtil.get(data,"values.status"));
        Long id = Long.valueOf(JsonUtil.get(data,"id").toString());
        String status = JsonUtil.get(data,"values.status").toString();
        if(!Arrays.asList(BasicStatus.SALES_ORDER_STATUS_CREATE,BasicStatus.SALES_ORDER_STATUS_ENABLE,BasicStatus.SALES_ORDER_STATUS_PLANNED).contains(status)){
            JsonResult.error(500,"当前状态是："+status+"不可更改！");
        }
        //判断所关联的计划是否是可更改状态
        List<HierInstance> hierInstanceList = hierInstanceDslServiceImpl.queryLink(productionModel,salesOrderModel,id);
        for(HierInstance hierInstance:hierInstanceList){
            JSONObject planJson = logicInstanceDslServiceImpl.queryJsonById(hierInstance.getContainerId());
            String planStatus = JsonUtil.get(planJson,"values.status").toString();
            String planApproveStatus = null==JsonUtil.get(planJson,"values.approveStatus")?"":JsonUtil.get(planJson,"values.approveStatus").toString();
            if(!BasicStatus.PRODUCTION_PLAN_STATUS_CREATE.equals(planStatus)||(BasicStatus.PRODUCTION_PLAN_STATUS_CREATE.equals(planStatus)&&Arrays.asList("",BasicStatus.APPROVE_STATUS_APPLY,BasicStatus.APPROVE_STATUS_REAPPLY).contains(planApproveStatus))){
                JsonResult.error(500,"计划："+JsonUtil.get(planJson,"values.planBatchNo")+"，当前状态是："+planStatus+",审批状态是："+planApproveStatus+",不可更改！");
            }
        }
        return JsonResult.success(resourceInstanceDslServiceImpl.updateById(data));
    }

    /**
     * 新增子计划
     * @param data 计划数据
     * @return 计划数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> addRouting(JSONObject data)  throws BusinessException{
        ValidateUtil.hasEmpty(JsonUtil.get(data,"values"),JsonUtil.get(data,"values.productId"),JsonUtil.get(data,"values.planType"),JsonUtil.get(data,"container.containerModel"),JsonUtil.get(data,"container.containerClassName"),JsonUtil.get(data,"container.containerId"),JsonUtil.get(data,"container.parentId"));
        Long productId = Long.valueOf(JsonUtil.get(data,"values.productId").toString());
        String planType = JsonUtil.get(data,"values.planType").toString();
        JSONObject proJson = resourceInstanceDslServiceImpl.queryById(productId);
        String routingClassName = JsonUtil.get(proJson,planType.contains("合批")?"values.routing":"values.middleRouting");
        if(StrUtil.isEmpty(routingClassName)){
            JsonResult.error(500,JsonUtil.get(proJson,"values.sf_name")+"没有配置工艺路径");
        }
        Routing routing = new Routing();
        JSONObject values = JsonUtil.toJSONObject(JsonUtil.get(data,"values"));
        routing.initRouting(routingClassName, JsonUtil.get(data,"values"));
        values.put("routingId",routing.getRouting().getId());
        JSONObject hierInsJson = JsonUtil.buildJson(new Object[]{"containerModel",JsonUtil.get(data,"container.containerModel"),"containerClassName",JsonUtil.get(data,"container.containerClassName"),"containerId",JsonUtil.get(data,"container.containerId"),"parentId",JsonUtil.get(data,"container.parentId"),"linkId",routing.getRouting().getId(),"linkType",routing.getRouting().getType(),"linkClassName",routing.getRouting().getClassName(),"values",values});
        JSONObject json = hierInstanceDslServiceImpl.convertToJson(hierInstanceDslServiceImpl.addChild(hierInsJson));
        return JsonResult.success(json);
    }

    /**
     * 处理工艺路径的workCenter
     * @param data 计划数据
     * @return 计划数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> dealRoutingWorkCenter(JSONObject data)  throws BusinessException{
        ValidateUtil.hasEmpty(JsonUtil.get(data,"routingId"),JsonUtil.get(data,"initWorkCenterNames"),JsonUtil.get(data,"delWorkCenterIds"));
        Long routingId = Long.valueOf(JsonUtil.get(data,"routingId").toString());
        Routing routing = new Routing();
        routing.setRouting(routingId);
        List<String> initWorkCenterNames = data.getJSONArray("initWorkCenterNames").toJavaList(String.class);
        List<Long> delIds = data.getJSONArray("delWorkCenterIds").toJavaList(Long.class);
        routing.initRoutingWorkCenter(initWorkCenterNames);
        routing.cancelRoutingWorkCenter(delIds);
        return JsonResult.success(routing.getRoutingJson());
    }
    /**
     * 初始化工艺路径
     * @param data 计划数据
     * @return 计划数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> initRouting(JSONObject data)  throws BusinessException{
        ValidateUtil.hasEmpty(JsonUtil.get(data,"values"),JsonUtil.get(data,"values.productId"),JsonUtil.get(data,"values.planType"));
        Long productId = Long.valueOf(JsonUtil.get(data,"values.productId").toString());
        JSONObject proJson = resourceInstanceDslServiceImpl.queryById(productId);
        String routingClassName = JsonUtil.get(proJson,"values.routing");
        Routing routing = new Routing();
        JSONObject values = JsonUtil.toJSONObject(JsonUtil.get(data,"values"));
        routing.initRouting(routingClassName, JsonUtil.get(data,"values"));
        values.put("routingId",routing.getRouting().getId());
        JSONObject hierInsJson = JsonUtil.buildJson(new Object[]{"containerModel",this.planModel,"containerClassName",this.planClassName,"containerId",this.planId,"parentId",JsonUtil.get(data,"parentId"),"linkId",routing.getRouting().getId(),"linkType",routing.getRouting().getType(),"linkClassName",routing.getRouting().getClassName(),"values",values});
        JSONObject json = hierInstanceDslServiceImpl.convertToJson(hierInstanceDslServiceImpl.addChild(hierInsJson));
        return JsonResult.success(json);
    }

    /** 弃用
     * 计划分页查询
     * @param actionData 分页查询参数
     * @return 返回分页查询routing数据
     * @throws BusinessException
     */
    public ResultInfo<?> planQueryByPage(ActionData<JSONObject> actionData) throws BusinessException{
        ResultInfo<?> resultInfo = hierInstanceBslServiceImpl.queryByPage(actionData);
        JSONObject data = JsonUtil.toJSONObject(resultInfo.getData());
        JSONArray records = JsonUtil.get(data,"records");
        List<Long> ids = records.stream()
                .filter(record->null!=JsonUtil.get(record,"linkId"))
                .map(record->Long.valueOf(JsonUtil.get(record,"linkId").toString()))
                .collect(Collectors.toList());
        if(CollectionUtil.isEmpty(ids)){
            data.put("records",new JSONArray());
        }else{
            data.put("records",routingInstanceDslServiceImpl.queryByIds(ids));
        }
        return JsonResult.success(data);
    }

    /**
     * 根据工艺路径ID获取工作中心
     * @param data 工艺路径ID
     * @return 工作中心实例列表
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> getWorkCenterByRoutingId(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(data.get("routingId"));
        Long routingId = Long.valueOf(JsonUtil.get(data,"routingId").toString());
        Routing routing = new Routing();
        routing.setRouting(routingId);
        List<WorkCenterInstance> workCenterInstanceList = routing.getWorkCenters().stream().map(workCenter->workCenter.getWorkCenter()).collect(Collectors.toList());
        return JsonResult.success(workCenterInstanceDslServiceImpl.getWorkCenterInsJsonObjectList(workCenterInstanceList));
    }

    /**
     * 删除计划
     * @param data 计划id和工艺路径id
     * @return 返回
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> deletePlan(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(data.get("id"));
        Long routingId = Long.valueOf(JsonUtil.get(data,"id").toString());
        Routing routing = new Routing();
        routing.setRouting(routingId);
        routing.delete();
        return JsonResult.success("成功");
    }

    /**
     * 执行计划
     * @param data 计划数据
     * @return 更新状态后的计划数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> executePlan(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(data.get("id"));
        Long routingId = Long.valueOf(JsonUtil.get(data,"id").toString());
        Routing routing = new Routing();
        routing.setRouting(routingId);
        routing.executeRouting();
        return JsonResult.success("执行成功！");
    }

    /**
     * 工单开工
     * @param data 工单数据
     * @return 工单数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> startWorkNotice(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(data.getJSONObject("values"),data.getJSONObject("values").get("routingId"),data.getJSONObject("values").get("workCenterId"));
        Long routingId = Long.valueOf(JsonUtil.get(data,"values.routingId").toString());
        Routing routing = new Routing();
        routing.setRouting(routingId);
        Long workCenterId = Long.valueOf(JsonUtil.get(data,"values.workCenterId").toString());
        WorkCenter workCenter = new WorkCenter();
        workCenter.setWorkCenter(workCenterId);
        workCenter.startWorkNotice(data);
        routing.setCurrentWorkCenters(Arrays.asList(workCenter));
        List<HierInstance> hierInstanceList = hierInstanceDslServiceImpl.queryLink(productionModel,routingModel,routingId);
        hierInstanceList.forEach(hierInstance -> updatePlanStatus(hierInstance.getContainerId(),BasicStatus.PRODUCTION_PLAN_STATUS_MAKING));
        return JsonResult.success(workCenter.getWorkNotice());
    }

    /**
     * 工单完成
     * @param data 工单数据
     * @return 工单数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> endWorkNotice(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(data.getJSONObject("values"),data.getJSONObject("values").get("routingId"),data.getJSONObject("values").get("workCenterId"));
        Long routingId = Long.valueOf(JsonUtil.get(data,"values.routingId").toString());
        Routing routing = new Routing();
        routing.setRouting(routingId);
        Long workCenterId = Long.valueOf(JsonUtil.get(data,"values.workCenterId").toString());
        WorkCenter workCenter = new WorkCenter();
        workCenter.setWorkCenter(workCenterId);
        workCenter.endWorkNotice(data);
        routing.finishWorkCenter(workCenter);
        JSONObject routingJson = routingUtil.getRoutingInsJsonObjectList(routing.getRouting());
        return JsonResult.success(workCenter.getWorkNotice());
    }

    /** 弃用
     * 添加生产通知单
     * @param data 生产通知单数据
     * @return 生产通知单数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> addWorkNotice(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(data.getJSONObject("values"),data.getJSONObject("values").get("workCenterId"));
        Long workCenterId = Long.valueOf(JsonUtil.get(data,"values.workCenterId").toString());
        List<HierInstance> hierList = hierInstanceDslServiceImpl.queryLink(routingModel,workCenterModel,workCenterId);
        if(CollectionUtil.isEmpty(hierList)){
            throw new BusinessException("工作中心未关联工艺路径");
        }
        data.getJSONObject("values").put("routingId",hierList.get(0).getContainerId());
        JSONObject workNoticeJson = logicInstanceDslServiceImpl.add(data);
        WorkCenter workCenter = new WorkCenter();
        workCenter.setWorkCenter(workCenterId);
        workCenter.addWorkNotice(workNoticeJson);
        return JsonResult.success(workNoticeJson);
    }

    /** 弃用
     * 执行下发生产通知单
     * @param data 生产通知单数据
     * @return 生产通知单数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> executeWorkNotice(JSONObject data) throws BusinessException{
        ValidateUtil.hasEmpty(data.getJSONObject("values"),data.getJSONObject("values").get("workCenterId"));
        Long workCenterId = Long.valueOf(JsonUtil.get(data,"values.workCenterId").toString());
        WorkCenter workCenter = new WorkCenter();
        workCenter.setWorkCenter(workCenterId);
        workCenter.executeWorkNotice(data);
        return JsonResult.success("成功");
    }

    /**
     * 分页查询，过滤掉被占用的数据
     * @param actionData 分页查询参数
     * @return 分页数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> queryTankNotLinkByPage(JSONObject actionData)  throws BusinessException {
        ValidateUtil.hasEmpty(actionData.get("workCenterId"));
        Long workCenterId = Long.valueOf(JsonUtil.get(actionData,"workCenterId").toString());
        List<HierInstance> hierList = hierInstanceDslServiceImpl.queryLink(noticeModel,noticeClassName,null,tankModel,tankClassName,null);
        List<String> linkIds = InstanceDataUtil.listLongToListString(InstanceDataUtil.getLinkIdsByHierList(hierList));
        dealCondition(actionData,linkIds,"id not in");
        WorkCenter workCenter = new WorkCenter();
        workCenter.setWorkCenter(workCenterId);
        List<String> materials = workCenter.getBOM().stream()
                .map(bom-> bom.getJSONObject("values").getString("productName"))
                .collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(materials)) {
            List<String> productIds = InstanceDataUtil.listLongToListString(queryProductIdByCategoryNames(materials));
            dealCondition(actionData, productIds, "productId in");
        }
        return tankInstanceBslServiceImpl.queryByPage(JsonUtil.toJavaBean(actionData,ActionData.class));
    }

    /**
     * 增加领退料记录
     * @param data 领退料记录
     * @return 领退料记录数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> addMaterialRecord(JSONObject data) throws BusinessException {
        ValidateUtil.hasEmpty(data.get("materialRecord"),data.get("workUnit"));
        JSONObject materialRecordJson = logicInstanceDslServiceImpl.add(JsonUtil.toJSONObject(JsonUtil.get(data,"materialRecord")));
        Long tankId = Long.valueOf(JsonUtil.get(materialRecordJson,"values.tankId").toString());
        Tank tank = new Tank();
        tank.setTank(tankId);
        BigDecimal weight = new BigDecimal(null==JsonUtil.get(materialRecordJson,"values.weight")?"0":JsonUtil.get(materialRecordJson,"values.weight").toString());
        if(Boolean.valueOf(JsonUtil.get(materialRecordJson,"values.pickStatus").toString())){
            tank.pick(weight);
        }else{
            tank.returnWeight(weight);
        }
        Long workCenterId = Long.valueOf(JsonUtil.get(data,"workUnit.values.workCenterId").toString());
        WorkCenter workCenter = new WorkCenter();
        workCenter.setWorkCenter(workCenterId);
        workCenter.addInputRecord(materialRecordJson);
        return JsonResult.success(materialRecordJson);
    }

    /**
     * 增加报工记录
     * @param data 报工记录
     * @return 报工记录数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> addWorkReportRecord(JSONObject data) throws BusinessException {
        ValidateUtil.hasEmpty(data.get("workReport"),data.get("workUnit"));
//        JSONObject tankJson = dealTank(data);
        JSONObject workReportJson = logicInstanceDslServiceImpl.add(JsonUtil.toJSONObject(JsonUtil.get(data,"workReport")));
//        workReportJson.getJSONObject("values").put("tankId",JsonUtil.get(tankJson,"id"));
//        logicInstanceDslServiceImpl.updateById(workReportJson);
        Long workCenterId = Long.valueOf(JsonUtil.get(data,"workUnit.values.workCenterId").toString());
        WorkCenter workCenter = new WorkCenter();
        workCenter.setWorkCenter(workCenterId);
        workCenter.addOutputRecord(workReportJson);
        return JsonResult.success(workReportJson);
    }

    /**
     * 提交报工记录
     * @param data 报工记录
     * @return 报工记录数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> submitWorkReportRecord(JSONObject data) throws BusinessException {
        ValidateUtil.hasEmpty(data.get("workReport"),data.get("workUnit"));ValidateUtil.hasEmpty(data.get("workReport"),data.get("workUnit"));
        JSONObject tankJson = dealTank(data);
        JSONObject workReportJson = JsonUtil.toJSONObject(JsonUtil.get(data,"workReport"));
        workReportJson.getJSONObject("values").put("tankId",JsonUtil.get(tankJson,"id"));
        workReportJson = logicInstanceDslServiceImpl.updateById(workReportJson);
        Long workCenterId = Long.valueOf(JsonUtil.get(data,"workUnit.values.workCenterId").toString());
        WorkCenter workCenter = new WorkCenter();
        workCenter.setWorkCenter(workCenterId);
        workCenter.outputSummary();
        String endStatus = JsonUtil.get(workReportJson,"values.endStatus").toString();
        Long routingId = Long.valueOf(JsonUtil.get(data,"workUnit.values.routingId").toString());
        List<HierInstance> hierInstanceList = hierInstanceDslServiceImpl.queryLink(productionModel,routingModel,routingId);
        hierInstanceList.forEach(hierInstance -> updatePlanStatus(hierInstance.getContainerId(),BasicStatus.PRODUCTION_PLAN_STATUS_IN_WAREHOUSE));
        if("完工".equals(endStatus)){
            Long workNoticeId = Long.valueOf(JsonUtil.get(data,"workUnit.values.workNoticeId").toString());
            workCenter.endWorkNotice(logicInstanceDslServiceImpl.queryJsonById(workNoticeId));
            Routing routing = new Routing();
            routing.setRouting(routingId);
            routing.finishWorkCenter(workCenter);
            hierInstanceList.forEach(hierInstance -> updatePlanStatus(hierInstance.getContainerId(),BasicStatus.PRODUCTION_PLAN_STATUS_FINISH));
        }
        return JsonResult.success(workReportJson);
    }

    /**
     * 删除报工记录
     * @param data 报工记录
     * @return 报工记录数据
     * @throws BusinessException
     */
    @Override
    @Transactional
    public ResultInfo<?> deleteWorkReportRecord(JSONObject data) throws BusinessException {
        ValidateUtil.hasEmpty(data.get("workReport"),data.get("workUnit"));
        if(ObjectUtil.isNotEmpty(JsonUtil.get(data,"workReport.values.tankId"))){
            Long tankId = data.getJSONObject("workReport").getJSONObject("values").getLong("tankId");
            tankInstanceDslServiceImpl.deleteByIds(Arrays.asList(tankId));
        }
        Long id = Long.valueOf(JsonUtil.get(data,"workReport.id").toString());
        logicInstanceDslServiceImpl.deleteByIds(Arrays.asList(id));
        Long workCenterId = Long.valueOf(JsonUtil.get(data,"workUnit.values.workCenterId").toString());
        WorkCenter workCenter = new WorkCenter();
        workCenter.setWorkCenter(workCenterId);
        workCenter.outputSummary();
        return JsonResult.success("删除成功");
    }

    /**
     * 处理桶实例数据
     * @param data 参数
     * @return 新增桶实例数据
     */
    private JSONObject dealTank(JSONObject data) {
        JSONObject tankValues = JsonUtil.pick(JsonUtil.toJSONObject(JsonUtil.get(data,"workReport.values")),new String[]{"productId","batchNo","tankNo"});
        tankValues.put("totalCapacity",JsonUtil.get(data,"workReport.values.weight"));
        tankValues.put("restCapacity",JsonUtil.get(data,"workReport.values.weight"));
        tankValues.put("tank",JsonUtil.get(data,"workUnit.values.routingId")+"-"+JsonUtil.get(data,"workUnit.values.workCenterId")+"-"+JsonUtil.get(data,"workUnit.values.workNoticeId"));
        JSONObject tankJson = JsonUtil.buildJson(new Object[]{"className",this.tankClassName,"type",this.tankType,"values",tankValues});
        tankJson = tankInstanceDslServiceImpl.add(tankJson);
        return tankJson;
    }

    /**
     * 工艺路径结束更新计划结束时间和状态
     * @param routingJson 工艺路径json数据
     */
    private void endPlan(JSONObject routingJson) {
        ValidateUtil.hasEmpty(routingJson.get("id"));
        List<JSONObject> planList = hierInstanceDslServiceImpl.convertToJson(
                hierInstanceDslServiceImpl.queryByContainerId(planModel,planId,planClassName,"parentId=='"+planParentId+"' and routingId==" +JsonUtil.get(routingJson,"id"))
        );
        if(CollectionUtil.isEmpty(planList)){
            throw new BusinessException("未找到所属计划");
        }
        JSONObject planJson = planList.get(0);
        JSONObject newValues = JsonUtil.buildJson(new Object[]{"status",endStatus,"endTime", DateUtil.now()});
        updatePlan(planJson,newValues);
    }

    /**
     * 更新计划数据
     * @param planJson 工艺路径json数据
     */
    private JSONObject updatePlan(JSONObject planJson,JSONObject newValues) {
        JSONObject values = JsonUtil.toJSONObject(JsonUtil.get(planJson,"values"));
        values.putAll(newValues);
        JSONObject hierInsJson = JsonUtil.buildJson(new Object[]{"containerModel",this.planModel,"containerClassName",this.planClassName,"containerId",this.planId,"parentId",JsonUtil.get(planJson,"parentId"),"id",JsonUtil.get(planJson,"id"),"values",values});
        JSONObject json = hierInstanceDslServiceImpl.convertToJson(hierInstanceDslServiceImpl.addChild(hierInsJson));
        return json;
    }

    /**
     * 处理条件数据
     * @param actionData 请求数据
     * @param ids id数组
     */
    private void dealCondition(JSONObject actionData, List<String> ids,String cond) {
        if(CollectionUtil.isNotEmpty(ids)){
            String conditon = null==JsonUtil.get(actionData,"condition")?"":JsonUtil.get(actionData,"condition");
            StringBuffer buffer = new StringBuffer(conditon+" &&"+cond+" (");
            conditon = InstanceDataUtil.condJoin(buffer, ids,null);
            actionData.put("condition",conditon);
        }
    }

    /**
     * 根据分类名称，查询符合分类的数据
     * @param categoryName 分类名称
     * @return 符合分类的数据id数组
     */
    private List<Long> queryProductIdByCategoryName(String categoryName){
        categoryName = "配碳".equals(categoryName)?"W+C":categoryName;
        List<JSONObject> materialList = resourceInstanceDslServiceImpl.query("sf_category=='"+categoryName+"'",materialClassName,null);
        List<Long> ids = materialList.stream().map(jsonObject -> jsonObject.getLong("id")).collect(Collectors.toList());
        return ids;
    }

    /**
     * 根据分类名称，查询符合分类的数据
     * @param categoryNames 分类名称
     * @return 符合分类的数据id数组
     */
    private List<Long> queryProductIdByCategoryNames(List<String> categoryNames){
        String conditon = "";
        if(CollectionUtil.isNotEmpty(categoryNames)){
            StringBuffer buffer = new StringBuffer(conditon+"sf_category in (");
            conditon = InstanceDataUtil.condJoin(buffer, categoryNames,null);
        }
        List<JSONObject> materialList = resourceInstanceDslServiceImpl.query(conditon,materialClassName,null);
        List<Long> ids = materialList.stream().map(jsonObject -> jsonObject.getLong("id")).collect(Collectors.toList());
        return ids;
    }

    /**
     * 处理合批计划的订单需求数据
     * @param id 计划id
     */
    private void dealRequiredOrder(Long id){
        JSONObject json = logicUtil.queryByIdAndHier(id);
        if(null==JsonUtil.get(json,"values.planType")||!JsonUtil.get(json,"values.planType").toString().contains("合批")){
            return;
        }
        List<JSONObject> hierContent = JsonUtil.toJSONArray(JsonUtil.get(json,"hier.content")).toJavaList(JSONObject.class);
        List<JSONObject> requireOrders = hierContent.stream().filter(hierJson->productionRequireOrderParentId.equals(hierJson.getString("parentId"))).collect(Collectors.toList());
        if(CollectionUtil.isEmpty(requireOrders)){
            throw new BusinessException("合批计划需求订单为空");
        }
        BigDecimal weight = hierContent.stream().filter(hierJson->productionOrderParentId.equals(hierJson.getString("parentId"))&&null!=JsonUtil.get(hierJson,"values.weight"))
                .map(hierJson->hierJson.getJSONObject("values").getBigDecimal("weight"))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        JSONObject requireOrder = JsonUtil.buildJson(new Object[]{"id",JsonUtil.get(requireOrders.get(0),"link.linkId"),"className",JsonUtil.get(requireOrders.get(0),"link.linkClassName"),"type",JsonUtil.get(requireOrders.get(0),"link.linkType"),"values",JsonUtil.buildJson(new Object[]{"orderFrom","需求订单","weight",weight})});
        resourceInstanceDslServiceImpl.updateById(requireOrder);
    }

}
